package com.day12_Thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @ClassName: CallableTest
 * @Author: zw
 * @Description: 出百万拳，行万里路；
 * @Create 2025/4/5-21:23
 * @Version 1.0
 */
public class CallableTest {
    // Thread类。Runnable接口前两种线程创建方式都存在一个问题： 假如线程执行完毕后有一些数据需要返回。他们重写的run方法均不能直接返回结果
    // 利用Callable接口和FutureTask类来创建多线程（第三种方法）
    // 1. 创建任务对象
    /**
     * 定义一个类实现Callable 接口，需要重写call方法，去封装要做的事情。和要返回的数据
     * 把Callable类型的对象封装成FutureTask（线程任务对象）
     */
    //2 把线程任务对象交给Thread对象
    //3. 调用Thread对象的start方法启动线程
    //4. 线程执行完毕后，通过FutureTask对象的get方法去获取线程任务执行的结果（返回值）
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 创建 Mycallable 类型的对象
        Callable<String> mc = new Mycallable(100);
        //把Callable类型的对象封装成FutureTask（线程任务对象）
        FutureTask<String> ft1 = new FutureTask<>(mc);
        /**
         * 线程任务对象作用：
         * 1， 本质是一个Runnable 线程任务对象。可以交给Thread 线程对象处理
         * 2.  可以获取线程执行完毕后的结果
         */
        // 把线程任务对象交给Thread对象
        Thread t1 = new Thread(ft1);
        // 调用Thread对象的start方法启动线程
        t1.start(); // 开启线程1
        // 线程执行完毕后，通过FutureTask对象的get方法去获取线程任务执行的结果（返回值）

        // 线程2
        Mycallable mc2 = new Mycallable(50);
        FutureTask<String> ft2 = new FutureTask<>(mc2);
        Thread t2 = new Thread(ft2);



        t2.start(); // 开启线程2
        String string1 = ft1.get(); // 这里如果发现第一个线程没有执行完毕，会让出cpu， 等一个线程执行完，才会往下执行
        String string2 = ft2.get();
        System.out.println(string1);
        System.out.println(string2);


    }
}
//1. 定义一个类实现Callable 接口，
class Mycallable implements Callable<String> {
    private int n;
    public  Mycallable(int n) {
        this.n = n;
    }
    // 重写call方法
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 0; i < n ; i++) {
            System.out.println(i);
            sum += i;
        }
        return "子线程计算的结果是：" + sum;
    }
}
